package com.megvii.corelib.loader;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import android.util.Log;

//暂时不考虑多线程调用
public abstract class ScrollLoader<T, D>
{
	private List<ScrollLoaderListener> listeners;
	private boolean requesting;
	private boolean testingRefresh;
	private boolean hasMore;

	public ScrollLoader()
	{
		super();
		listeners = new ArrayList<>();
		requesting = false;
		hasMore = true;
	}

	public void requestMore()
	{
		if (requesting)
		{
			return;
		}
		if (hasMore)
		{
			Log.w("koala scroll", "requestMore");
			requestForFetchMore();
		}
	}

	public void refresh()
	{
		if (requesting)
		{
			return;
		}
		Log.w("koala scroll", "refresh");
		requestForTestRefresh();
	}

	protected void onResponse(T response)
	{
		String error = getResponseError(response);
		if (error == null)
		{
			boolean notifyDataChange = false;
			if (testingRefresh)
			{
				if (isReponseNeedRefresh(response))
				{
					clear();
					hasMore = append(response);
					notifyDataChange = true;
				}
			}
			else
			{
				hasMore = append(response);
				notifyDataChange = true;
			}
			if (notifyDataChange)
			{
				for (ScrollLoaderListener listener : listeners)
				{
					listener.onDataChange(getData(), hasMore);
				}
			}
			else
			{
				notifyNoChange();
			}
		}
		else
		{
			for (ScrollLoaderListener listener : listeners)
			{
				listener.onError(error);
			}
		}
		requesting = false;
	}

	protected void onError(String error)
	{
		for (ScrollLoaderListener listener : listeners)
		{
			listener.onError(error);
		}
		requesting = false;
	}

	public void addListener(ScrollLoaderListener listener)
	{
		listeners.add(listener);
	}

	public void removeListener(ScrollLoaderListener listener)
	{
		Iterator<ScrollLoaderListener> iterator = listeners.iterator();
		while (iterator.hasNext())
		{
			ScrollLoaderListener next = iterator.next();
			if (next == listener)
			{
				iterator.remove();
			}
		}
	}

	/**
	 * 返回null说明没有错误
	 * @param response
	 * @return
	 */
	abstract protected String getResponseError(T response);

	abstract protected boolean append(T response);

	protected void requestForFetchMore()
	{
		requesting = true;
		testingRefresh = false;
	}
	
	protected void requestForTestRefresh()
	{
		requesting = true;
		testingRefresh = true;
	}

	abstract protected boolean isReponseNeedRefresh(T response);

	protected void clear()
	{
		hasMore = true;
	}

	public boolean isHasMore()
	{
		return hasMore;
	}
	
	public boolean isRequesting()
	{
		return requesting;
	}

	protected abstract D getData();

	private void notifyNoChange()
	{
		for (ScrollLoaderListener listener : listeners)
		{
			listener.onNoChange(hasMore);
		}
	}
}